package com.sky.interceptor;

import com.sky.constant.JwtClaimsConstant;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import com.sky.utils.ThreadLocalUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 客户端登录校验拦截器
 *
 * @Author Vsunks.v
 * @Date 2023/5/6 17:34
 * @Blog blog.sunxiaowei.net/996.mba
 * @Description: 客户端登录校验拦截器
 */
@Slf4j
@Component
public class JwtTokenUserInterceptor implements HandlerInterceptor {

    @Autowired
    JwtProperties jwtProperties;

    /**
     * 在处理请求之前，校验
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  要请求的资源封装的对象
     * @return true表示放行，后续的资源才能被访问到；返回false表示拦截不放行，也就无法访问后续的资源
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 1. 放行非动态资源
        if (!(handler instanceof HandlerMethod)) {
            // 直接放行
            return true;
        }

        // 2. 校验令牌
        // 2.1 获取令牌
        String token = request.getHeader(jwtProperties.getUserTokenName());
        log.info("C端操作，{}为：{}", jwtProperties.getUserTokenName(), token);

        // 2.2 解析并校验令牌
        try {
            // 2.3 校验通过，放行
            Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
            // 获取当前登录用户的id并设置进线程容器
            Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
            ThreadLocalUtil.setCurrentId(userId);
            log.info("C端登录校验通过，放行！登录用户的id为：{}",userId);
            // 放行
            return true;

        } catch (Exception e) {
            // 2.4 校验不通过，不放行。设置401响应状态码（无权限访问）
            response.setStatus(401);
            log.info("C端登录校验不通过，跳转到登录页面。");
            return false;
        }
    }
}
